import { Controller,Post,Body } from '@nestjs/common';
import { ApiBasicAuth, ApiTags, ApiOperation, ApiProperty  } from '@nestjs/swagger'
import { InjectModel } from '@nestjs/mongoose'
import { IsNotEmpty } from 'class-validator'
import { jwtConstants } from '../config'
import * as bcrypt from 'bcryptjs';
import * as JWT from 'jsonwebtoken'
// 定义接口文档与数据验证
class userCatDto{
  // 接口文档展示信息 description 示例值  example 字段描述  required：true 则展示为必填
  // 文档地址：https://docs.nestjs.cn/9/recipes?id=swagger
  @ApiProperty({ description:'',example:'账号(required)', required:true })
  // 使用管道进行验证
  // 文档地址：https://docs.nestjs.cn/9/techniques?id=%e9%aa%8c%e8%af%81
  @IsNotEmpty({message:'账号必填'})
  username: string
  @ApiProperty({ description:'',example:'密码(required)', required:true})
  @IsNotEmpty({message:'密码必填'})
  password: string
  @ApiProperty({ description:'',example:'身份标识(required) 0 游客 1 管理员', required:true})
  @IsNotEmpty({message:'身份标识必填'})
  userSession: string
}
class loginCatDto{
  // 接口文档展示信息 description 示例值  example 字段描述  required：true 则展示为必填
  @ApiProperty({ description:'',example:'账号(required)' , required:true})
  // 使用管道进行
  @IsNotEmpty({message:'账号必填'})
  username: string
  @ApiProperty({ description:'',example:'密码(required)', required:true})
  @IsNotEmpty({message:'密码必填'})
  password: string
  tokens: string
}
// 接口文档接口组标题
@ApiTags('注册/登录')
// 登录接口前缀
@Controller('login')
export class LoginController {
  constructor(
    //使用InjectModel装饰器将studentsModel服务注入，该服务将负责数据存储和检索
    @InjectModel('Cat') private readonly studentsModel,
) {}

@Post('users')
// 注册接口
@ApiOperation({ summary: '注册账号接口' })
async users(@Body() body:userCatDto,){
  // 进行散列不可逆加密 10的盐长
  body.password = await bcrypt.hashSync(body.password, 10)
  // 为每一个注册者设定权限 // 也可根据前端传递字段去单独识别
  
  const user = {
    username: body.username,
    password: body.password,
    userSession:body.userSession,
    startTime: Date.now(),
    lastTime: Date.now()
  }
  // 优先查询用户名是否重复
  // "user.name =name"，{name:"Timber"}
  
  // 不直接使用传递的数据，让查询语句的查询目标为变量值，防止语句攻击
  const username = body.username
  const repeat = await this.studentsModel.find({username:username})  
  if (repeat.length) return {message:'用户名已存在',status:'201'}
  // 对注册数据进行写入
  const result = await this.studentsModel.create(user)
  
  if (result) return {message:'注册成功',status:'200'}
  
  
  return {status:'201',message:'服务端错误'}
  }

// 登录接口
@Post('siginIn')
@ApiOperation({ summary: '登录接口' })
async logins(@Body() body:loginCatDto,){
  // 根据用户名查询数据
  const result = await this.studentsModel.find({username: body.username});  
  if (!result.length)  return {status:'201',data:[],message:'用户名/密码错误'}  
  // 对输入密码进行数据库加密后密码比较
  const compareResult = bcrypt.compareSync(body.password, result[0].password)
  // 判断用户名与密码是否存在/一致
  if (!compareResult||!result.length)  return {status:'201',data:[],message:'用户名/密码错误'}
  // 进行tokwn生成
  const token = JWT.sign(body, jwtConstants.secret, {
    expiresIn: jwtConstants.expiresIn,
  })
  // 用户名已做限制，是唯一的
  result[0].tokens='Bearer '+token
  // 此处希望存储token做为后续接口识别用户字段
  await result[0].save()
  if (result) return {status:'200',data:[],token:token,message:'登录成功'}
  }
}
